﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Text;

namespace SIEGEwebapp
{
    public partial class ModeloMatematicos : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public void APIErrorCheck(IntPtr pEnv, int nErr)
        {
            if (nErr > 0)
            {
                StringBuilder cMessage = new StringBuilder(lindo.LS_MAX_ERROR_MESSAGE_LENGTH);
                lindo.LSgetErrorMessage(pEnv, nErr, cMessage);
                this.lblMsg.Text = cMessage.ToString();
            }
        }

        protected void btnCargarDatos_Click(object sender, EventArgs e)
        {
            string InfCon;
            InfCon = @"Data Source = MARY\SQLExpress2008; Initial Catalog = AplicacionWeb; Integrated Security = True";
            System.Data.DataTable dt = new DataTable();
            using (SqlConnection oCon = new SqlConnection(InfCon))
            {

                SqlCommand oCom;
                string SelectSQL = "SELECT * FROM funcionobjetivo";
                oCom = new SqlCommand(SelectSQL, oCon);
                int numVariables = 0;
                SqlDataReader oLector;
                oCon.Open();
                oLector = oCom.ExecuteReader();
                while (oLector.Read())
                {
                    numVariables++;
                    int idx = (int)oLector["idx"];
                    double valor = (double)oLector["valorx"];
                    ((TextBox)this.FindControl("txtFunObj" + idx)).Text = valor.ToString();
                }
                oLector.Close();
                HiddenField1.Value = numVariables.ToString();
                SelectSQL = "SELECT * FROM variablesXrestriccion";

                oCom.CommandText = SelectSQL;
                //SqlDataReader oLector;

                oLector = oCom.ExecuteReader();
                while (oLector.Read())
                {
                    int idrestriccion = (int)oLector["idrestriccion"];
                    int idx = (int)oLector["idx"];
                    double valorxr = (double)oLector["valorxr"];
                    ((TextBox)this.FindControl(string.Format("txtRest{0}{1}", idrestriccion, idx))).Text = valorxr.ToString();
                }
                oLector.Close();
                ///agregar limites
                ///
                SelectSQL = "SELECT * FROM cota";
                oCom.CommandText = SelectSQL;
                string inferior = string.Empty;
                string superior = string.Empty;

                oLector = oCom.ExecuteReader();
                while (oLector.Read())
                {
                    int idcota = (int)oLector["idcota"];
                    bool infinferior = (bool)oLector["valorinfinitoinf"];
                    bool infsuperior = (bool)oLector["valorinfinitosup"];
                    double valorcotainf = (double)oLector["valorcotainf"];
                    double valorcotasup = (double)oLector["valorcotasup"];



                    inferior += "X" + idcota.ToString() + ">" + ((infinferior) ? "inf" : valorcotainf.ToString()) + ";";
                    superior += "X" + idcota.ToString() + "<" + ((infsuperior) ? "inf" : valorcotasup.ToString()) + ";";

                }
                oLector.Close();
                lblRes7.Text = System.Security.SecurityElement.Escape(inferior) + "   " + System.Security.SecurityElement.Escape(superior);


                oCom.CommandText = "Select * from [restricciones]";
                SqlDataAdapter adap = new SqlDataAdapter(oCom);
                adap.Fill(dt);



                oCon.Close();
            }
            int NoneZeroValue = 0;
            string firstNoneZeroElement = string.Empty;
            string NoneZeroElementLenByCol = string.Empty;
            string NoneZeroElementPosByRow = string.Empty;
            string NoneZeroElementByCol = string.Empty;
            for (int i = 1; i < 5; i++)
            {
                bool findFirstInCol = true;
                int NoneZeroElementLenInCol = 0;
                for (int j = 1; j < 4; j++)
                {
                    string valor = ((TextBox)this.FindControl(string.Format("txtRest{0}{1}", j, i))).Text;
                    if (valor != "0")
                    {
                        NoneZeroValue++;
                        NoneZeroElementLenInCol++;
                        if (findFirstInCol)
                        {
                            firstNoneZeroElement += (NoneZeroValue - 1) + ((i < 4) ? "," : string.Empty);
                            findFirstInCol = false;
                        }
                        NoneZeroElementByCol += valor + ",";
                        NoneZeroElementPosByRow += (j - 1) + ",";
                        /*
                          Los coeficientes que NO son cero por columna 
                        double[] adA = new double[] { 1, 1, 1, 1, 1, 1, 1, 1 };

                         La posición por fila de los elementos que NO son cero 
                        int[] anRowX = new int[] { 0, 1, 0, 1, 2, 0, 2, 0 }
                                     */
                    }
                }
                NoneZeroElementLenByCol += NoneZeroElementLenInCol + ((i < 4) ? "," : string.Empty);
            }
            txtResultado6.Text = string.Empty;
            foreach (System.Data.DataRow dr in dt.Select(string.Empty, "idrestriccion"))
            {
                string valorrestriccion = dr["valorrestriccion"].ToString();
                string tiporestriccion = dr["tiporestriccion"].ToString();
                ((TextBox)this.FindControl(string.Format("Textcoef{0}", dr["idrestriccion"]))).Text = valorrestriccion;
                txtResultado6.Text += tiporestriccion;
                switch (tiporestriccion)
                {
                    case "E": tiporestriccion = "="; break;
                    case "G": tiporestriccion = ">="; break;
                    case "L": tiporestriccion = "<="; break;
                }
                ((Label)this.FindControl(string.Format("lbltipo{0}", dr["idrestriccion"]))).Text = tiporestriccion;

            }
            //dt.Rows

            txtResultado1.Text = dt.Rows.Count.ToString();
            txtResultado2.Text = NoneZeroValue.ToString();
            txtResultado3.Text = firstNoneZeroElement;
            txtResultado4.Text = NoneZeroElementLenByCol;
            txtResultado5.Text = NoneZeroElementPosByRow.Trim(',');
            NoneZeroElementByCol.Trim(',');


        }

        protected void btnOptimizar_Click(object sender, EventArgs e)
        {
            int nErrorCode = lindo.LSERR_NO_ERROR;

            /* Número de restricciones */
            int nCons = int.Parse(txtResultado1.Text);

            /* Número de variables de decisión */
            int nVars = int.Parse(HiddenField1.Value);

            /* Se declara una variable que nos va a permitir comunicarnos con LINDO */
            IntPtr pEnv = (IntPtr)0;

            /* Se declara una variable que nos va a permitir tratar con el modelo */
            IntPtr pModel = (IntPtr)0;

            int nSolStatus = lindo.LS_STATUS_UNKNOWN;

            StringBuilder LicenseKey = new StringBuilder(lindo.LS_MAX_ERROR_MESSAGE_LENGTH);

            /* >>> PASO 1 <<< Lograr la comunicación con LINDO */
            nErrorCode = lindo.LSloadLicenseString(@"C:\Lindoapi\license\lndapi90.lic", LicenseKey);
            APIErrorCheck(pEnv, nErrorCode);

            pEnv = lindo.LScreateEnv(ref nErrorCode, LicenseKey.ToString());
            if (nErrorCode == lindo.LSERR_NO_VALID_LICENSE)
            {
                lblMsg.Text = "¡LICENCIA NO VÁLIDA!\n";
                return;
            }
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 2 <<< Crear el modelo */
            pModel = lindo.LScreateModel(pEnv, ref nErrorCode);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 3 <<< Especificar el modelo */

            /* El tipo de optimización */
            int nDir = lindo.LS_MIN;

            /* El término constante de la función objetivo */
            double dObjConst = 0;

            /* Los coeficientes de la función objetivo */
            double[] adC = new double[nVars];
            adC[0] = double.Parse(txtFunObj1.Text);//12;
            adC[1] = double.Parse(txtFunObj2.Text);// 9;
            adC[2] = double.Parse(txtFunObj3.Text);//11;
            adC[3] = double.Parse(txtFunObj4.Text);//4;


            /* El lado derecho de las restricciones */
            double[] adB = new double[nCons];
            adB[0] = double.Parse(Textcoef1.Text);//50;
            adB[1] = double.Parse(Textcoef2.Text);//22.5;
            adB[2] = double.Parse(Textcoef3.Text);//15;


            /* Los tipos de restricciones */
            string acConTypes = txtResultado6.Text;//"EGL";


            /* El número de elementos que NO son cero en la matriz de restricciones */
            int nNZ = int.Parse(txtResultado2.Text);//8;

            /* La posición del primer elemento NO cero de cada columna */
            int[] anBegCol = new int[txtResultado3.Text.Split(',').Length + 1];// { 0, 2, 5, 7, nNZ };
            int i = 0;
            foreach (string anbegstring in txtResultado3.Text.Split(','))
            {
                anBegCol[i] = int.Parse(anbegstring);
                i++;
            }
            anBegCol[i] = nNZ;


            /* La longitud de cada columna en cuanto a los elementos que NO son cero */
            int[] pnLenCol = new int[txtResultado4.Text.Split(',').Length];// { 2, 3, 2, 1 };
            i = 0;
            foreach (string pnLenColstring in txtResultado4.Text.Split(','))
            {
                pnLenCol[i] = int.Parse(pnLenColstring);
                i++;
            }
            /* Los coeficientes que NO son cero por columna */
            double[] adA = new double[nNZ];// { 1, 1, 1, 1, 1, 1, 1, 1 };
            int NoneZeroValue = 0;
            for (int n = 1; n < 5; n++)
            {

                for (int j = 1; j < 4; j++)
                {
                    string valor = ((TextBox)this.FindControl(string.Format("txtRest{0}{1}", j, n))).Text;
                    if (valor != "0")
                    {

                        adA[NoneZeroValue] = double.Parse(valor);
                        NoneZeroValue++;

                    }
                }
            }
            /* La posición por fila de los elementos que NO son cero */

            int[] anRowX = new int[txtResultado5.Text.Split(',').Length];// { 0, 1, 0, 1, 2, 0, 2, 0 };

            i = 0;
            foreach (string pnLenColstring in txtResultado5.Text.Split(','))
            {
                anRowX[i] = int.Parse(pnLenColstring);
                i++;
            }
            /* Cotas inferiores y superiores de cada variable */
            double[] pdLower = new double[] { 0, 0, 0, 7.5 };
            //double CapacidadMax = double.Parse(txtCapMax.Text);
            double[] pdUpper = new double[] { lindo.LS_INFINITY, lindo.LS_INFINITY,
                                              lindo.LS_INFINITY, lindo.LS_INFINITY };

            /* Nombres de variables y restricciones */
            string[] varnames = new string[] { "X1", "X2", "X3", "X4" };
            string[] connames = new string[] { "R1", "R2", "R3" };

            /* Cargamos el modelo */
            nErrorCode = lindo.LSloadLPData(pModel, nCons, nVars, nDir,
                dObjConst, adC, adB, acConTypes, nNZ, anBegCol,
                pnLenCol, adA, anRowX, pdLower, pdUpper);
            APIErrorCheck(pEnv, nErrorCode);

            nErrorCode = lindo.LSloadNameData(pModel, "Plan de Producción", null, null, null,
            null, connames, varnames, null);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 4 <<< Correr el modelo matemático */
            nErrorCode = lindo.LSoptimize(pModel, lindo.LS_METHOD_PSIMPLEX, ref nSolStatus);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 5 <<< Tomar la salida de la optimización */

            /* Se toma el valor de la función objetivo */
            double dObj = 0;
            nErrorCode = lindo.LSgetInfo(pModel, lindo.LS_DINFO_POBJ, ref dObj);
            APIErrorCheck(pEnv, nErrorCode);
            // Se atrapa el valor de la función objetivo
            this.txtSolucionOptima.Text = dObj.ToString();

            /* Se toman los valores de las variables */
            double[] adX = new double[nVars];
            nErrorCode = lindo.LSgetPrimalSolution(pModel, adX);
            APIErrorCheck(pEnv, nErrorCode);

            TextSolOpt1.Text = adX[0].ToString();
            TextSolOpt2.Text = adX[1].ToString();
            TextSolOpt3.Text = adX[2].ToString();
            TextSolOpt4.Text = adX[3].ToString();



            /* >>> PASO 6 <<< Borramos el modelo de LINDO y cortamos la comunicación con el SOLVER */
            nErrorCode = lindo.LSdeleteModel(ref pModel);
            nErrorCode = lindo.LSdeleteEnv(ref pEnv);
        }

        protected void txtResultado3_TextChanged(object sender, EventArgs e)
        {

        }

        protected void txtResultado7_TextChanged(object sender, EventArgs e)
        {

        }

        protected void Textcoef3_TextChanged(object sender, EventArgs e)
        {

        }
    }

}